package com.ocom.common.utils;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 封装http get post
 */
@Slf4j
@SuppressWarnings("all")
public class HttpUtils {

	/**
	 * get方法
	 * 
	 * @param url
	 * @return
	 */
	public static Map<String, Object> doGet(String url) {

		Map<String, Object> map = new HashMap<>();
		CloseableHttpClient httpClient = HttpClients.createDefault();

		RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000) // 连接超时
				.setConnectionRequestTimeout(5000)// 请求超时
				.setSocketTimeout(5000).setRedirectsEnabled(true) // 允许自动重定向
				.build();

		HttpGet httpGet = new HttpGet(url);
		httpGet.setConfig(requestConfig);

		try {
			HttpResponse httpResponse = httpClient.execute(httpGet);
			if (httpResponse.getStatusLine().getStatusCode() == 200) {

				String jsonResult = EntityUtils.toString(httpResponse.getEntity());
				map = com.ocom.common.utils.GsonBuilder.build().fromJson(jsonResult, map.getClass());
			}

		} catch (Exception e) {
			StackTraceElement stackTraceElement = e.getStackTrace()[0];
			log.error("doGet-" + stackTraceElement.getMethodName() + "--" + stackTraceElement.getLineNumber());
		} finally {
			try {
				httpClient.close();
			} catch (Exception e) {
			}
		}
		return map;
	}

	/**
	 * 封装post
	 * 
	 * @return
	 */
	public static String doPost(String url, String data, int timeout) {
		CloseableHttpClient httpClient = HttpClients.createDefault();
		// 超时设置

		RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(timeout) // 连接超时
				.setConnectionRequestTimeout(timeout)// 请求超时
				.setSocketTimeout(timeout).setRedirectsEnabled(true) // 允许自动重定向
				.build();

		HttpPost httpPost = new HttpPost(url);
		httpPost.setConfig(requestConfig);
		httpPost.addHeader("Content-Type", "text/html; chartset=UTF-8");

		if (data != null && data instanceof String) { // 使用字符串传参
			StringEntity stringEntity = new StringEntity(data, "UTF-8");
			httpPost.setEntity(stringEntity);
		}

		try {

			CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
			HttpEntity httpEntity = httpResponse.getEntity();
			if (httpResponse.getStatusLine().getStatusCode() == 200) {
				String result = EntityUtils.toString(httpEntity);
				return result;
			}

		} catch (Exception e) {
			StackTraceElement stackTraceElement = e.getStackTrace()[0];
			log.error("doPost-" + stackTraceElement.getMethodName() + "--" + stackTraceElement.getLineNumber());

		} finally {
			try {
				httpClient.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		return null;

	}


	/**
	 * 发送post请求
	 * @param url  路径
	 * @param jsonObject  参数(json类型)
	 * @param encoding 编码格式
	 * @return
	 * @throws ParseException
	 * @throws IOException
	 */
	public static String doPostBodyData(String url, JSONObject jsonObject, String encoding) throws ParseException, IOException {
		String body = "";

		//创建httpclient对象
		CloseableHttpClient client = HttpClients.createDefault();
		//创建post方式请求对象
		HttpPost httpPost = new HttpPost(url);

		//装填参数
		StringEntity s = new StringEntity(jsonObject.toString(), "utf-8");
		s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,
				"application/json"));
		//设置参数到请求对象中
		httpPost.setEntity(s);

		System.out.println("请求地址："+url);
//        System.out.println("请求参数："+nvps.toString());

		//设置header信息
		//指定报文头【Content-type】、【User-Agent】
//        httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
		httpPost.setHeader("Content-type", "application/json");
		httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

		//执行请求操作，并拿到结果（同步阻塞）
		CloseableHttpResponse response = client.execute(httpPost);
		//获取结果实体
		HttpEntity entity = response.getEntity();
		if (entity != null) {
			//按指定编码转换结果实体为String类型
			body = EntityUtils.toString(entity, encoding);
		}
		EntityUtils.consume(entity);
		//释放链接
		response.close();
		return body;
	}


	public static byte[] doPostBodyEntity(String url, JSONObject jsonObject, String encoding) throws Exception {
		String body = "";

		//创建httpclient对象
		CloseableHttpClient client = HttpClients.createDefault();
		//创建post方式请求对象
		HttpPost httpPost = new HttpPost(url);

		//装填参数
		StringEntity s = new StringEntity(jsonObject.toString(), "utf-8");
		s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,
				"application/json"));
		//设置参数到请求对象中
		httpPost.setEntity(s);

		System.out.println("请求地址："+url);
//        System.out.println("请求参数："+nvps.toString());

		//设置header信息
		//指定报文头【Content-type】、【User-Agent】
//        httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
		httpPost.setHeader("Content-type", "application/json");
		httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

		//执行请求操作，并拿到结果（同步阻塞）
		CloseableHttpResponse response = client.execute(httpPost);
		//获取结果实体
		HttpEntity entity = response.getEntity();
		byte[] bytes = Base64Util.readInputStream(entity.getContent());
		//释放链接
		response.close();
		return bytes;
	}

	/**
	 * body 带header
	 * @param url
	 * @param header
	 * @param jsonObject
	 * @return
	 * @throws ParseException
	 * @throws IOException
	 */
	public static String doPostBodyData(String url,  Map<String,String> header, JSONObject jsonObject ) throws ParseException, IOException {
		String body = "";

		//创建httpclient对象
		CloseableHttpClient client = HttpClients.createDefault();
		//创建post方式请求对象
		HttpPost httpPost = new HttpPost(url);

//		httpPost.setEntity(new UrlEncodedFormEntity(list,HTTP.UTF_8));

		//装填参数
		StringEntity s = new StringEntity(jsonObject.toString(), "utf-8");
		s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,
				"application/json"));
		//设置参数到请求对象中
		httpPost.setEntity(s);
		System.out.println("请求地址："+url);
//        System.out.println("请求参数："+nvps.toString());

		//设置header信息
		//指定报文头【Content-type】、【User-Agent】
//        httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
		httpPost.setHeader("Content-type", "application/json");
		httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

		if(!header.isEmpty()){
			for(Map.Entry entry: header.entrySet()) {
				httpPost.setHeader((String) entry.getKey(),(String) entry.getValue());
			}
		}

		//执行请求操作，并拿到结果（同步阻塞）
		CloseableHttpResponse response = client.execute(httpPost);
		//获取结果实体
		HttpEntity entity = response.getEntity();
		if (entity != null) {
			//按指定编码转换结果实体为String类型
			body = EntityUtils.toString(entity, "utf-8");
		}
		EntityUtils.consume(entity);
		//释放链接
		response.close();
		return body;
	}


	//body
	public static String SmsPost(String url,String token, JSONObject jsonObject ) throws IOException {
		MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
		OkHttpClient client = new OkHttpClient();

		RequestBody body = RequestBody.create(mediaType, jsonObject.toString());

		Request request = new Request.Builder()
				.url(url)
				.addHeader("token", token)
				.post(body)
				.build();
		//同步
		Response response = client.newCall(request).execute();
		if (response.isSuccessful()) {
			return response.body().string();
		} else {
			throw new IOException("Unexpected code " + response);
		}
	}



	/**
	 *
	 * @param POST_URL
	 * @param token
	 * @return
	 * @throws IOException
	 */
	private static boolean sendHttpsPost(String POST_URL,String body)throws IOException{

		boolean returnVal=false;

		URL myURL = new URL(POST_URL);

		HttpsURLConnection con = (HttpsURLConnection) myURL.openConnection();

		HostnameVerifier hostNameVerify = new HostnameVerifier()
		{
			/**
			 * Always return true
			 */
			public boolean verify(String urlHostName, SSLSession session)
			{
				return true;
			}
		};
		//HttpsURLConnection.setDefaultHostnameVerifier(hostNameVerify);
		con.setHostnameVerifier(hostNameVerify);
		try {
			con.setSSLSocketFactory(init());
		} catch (Exception e1) {
			// throw out the exception
			throw new IOException(e1);
		}

		con.setDoOutput(true);
		con.setDoInput(true);
		con.setRequestMethod("POST");
		con.setUseCaches(false);
		con.setInstanceFollowRedirects(true);
		con.setRequestProperty("Content-Type "," application/x-www-form-urlencoded ");

		con.connect();

		DataOutputStream out = new DataOutputStream(con.getOutputStream());

		String content = "authenticityToken="+ URLEncoder.encode(body, "utf-8");

		out.writeBytes(content);

		out.flush();
		out.close();

		BufferedReader reader = new BufferedReader(new InputStreamReader(
				con.getInputStream()));
		String line;

		while ((line = reader.readLine()) != null) {

			if(line.equalsIgnoreCase("ok"))
				returnVal=true;
			else
				returnVal=false;
		}
		reader.close();
		con.disconnect();
		return returnVal;
	}


	public static SSLSocketFactory init() throws Exception {

		class MyX509TrustManager implements X509TrustManager {

			public MyX509TrustManager() throws Exception {
				// do nothing
			}

			@Override
			public void checkClientTrusted(X509Certificate[] chain,
										   String authType) throws CertificateException {

			}

			@Override
			public void checkServerTrusted(X509Certificate[] chain,
										   String authType) throws CertificateException {

                /*
                log.info("authType is " + authType);
                log.info("cert issuers");

                try{
                    for (int i = 0; i < chain.length; i++) {
                        log.info("\t" + chain[i].getIssuerX500Principal().getName());
                        log.info("\t" + chain[i].getIssuerDN().getName());
                        chain[i].checkValidity();
                    }
                }catch(CertificateExpiredException ex){
                    log.error("checkDate: Certificate has expired");
                }catch(CertificateNotYetValidException yet){
                    log.error("checkDate: Certificate is not yet valid");
                }catch(Exception ee){
                    log.error("Error: "+ee.getMessage());
                }*/

			}

			@Override
			public X509Certificate[] getAcceptedIssuers() {
				return new X509Certificate[] {};
			}
		}
		TrustManager[] tm = { new MyX509TrustManager() };

		System.setProperty("https.protocols", "TLSv1");
		SSLContext sslContext = SSLContext.getInstance("TLSv1","SunJSSE");
		sslContext.init(null, tm, new java.security.SecureRandom());
		SSLSocketFactory ssf = sslContext.getSocketFactory();

		return ssf;
	}

	private static TrustManager myX509TrustManager = new X509TrustManager() {

		@Override
		public X509Certificate[] getAcceptedIssuers() {
			return null;
		}

		@Override
		public void checkServerTrusted(X509Certificate[] chain, String authType)
				throws CertificateException {
		}

		@Override
		public void checkClientTrusted(X509Certificate[] chain, String authType)
				throws CertificateException {
		}
	};


	public static  String SendHttpsPOST(String url, List<NameValuePair> param, String data,Map<String,String> header)
	{

		StringBuffer sb=new StringBuffer();

		//使用此工具可以将键值对编码成"Key=Value&Key2=Value2&Key3=Value3”形式的请求参数
		String requestParam = URLEncodedUtils.format(param, "UTF-8");
		try {
			//打开连接
			//要发送的POST请求url?Key=Value&Key2=Value2&Key3=Value3的形式
			URL requestUrl = new URL(url + "?" + requestParam);
			HttpsURLConnection httpsConn = (HttpsURLConnection)requestUrl.openConnection();

			// 设置允许输出
			httpsConn.setDoOutput(true);
			// 设置允许输入
			httpsConn.setDoInput(true);

			// 设置不用缓存
			httpsConn.setUseCaches(false);
			// 设置传递方式
			httpsConn.setRequestMethod("POST");
			// 设置维持长连接
			httpsConn.setRequestProperty("Connection", "Keep-Alive");

			// 设置文件类型:
			httpsConn.setRequestProperty("Content-Type","application/json; charset=UTF-8");

			httpsConn.setRequestProperty("Charset", "UTF-8");

			// 转换为字节数组
			byte[] data1 = (data.toString()).getBytes();
			// 设置文件长度
			httpsConn.setRequestProperty("Content-Length", String.valueOf(data1.length));

			if(!header.isEmpty()){
				for(Map.Entry entry: header.entrySet()) {
					httpsConn.setRequestProperty((String) entry.getKey(),(String) entry.getValue());
				}
			}

			// 设置接收类型否则返回415错误
			httpsConn.setRequestProperty("accept","*/*");//此处为暴力方法设置接受所有类型，以此来防范返回415;
		//	httpsConn.setRequestProperty("accept","application/json");

			DataOutputStream out = new DataOutputStream(
					httpsConn.getOutputStream());

			// 写入请求的字符串
			out.write((data.toString()).getBytes());

			out.flush();
			out.close();

			System.out.println(httpsConn.getResponseCode());
			// 请求返回的状态
			if (HttpURLConnection.HTTP_OK == httpsConn.getResponseCode()){
				System.out.println("连接成功");
				// 请求返回的数据
				InputStream in1 = httpsConn.getInputStream();
				try {
					String readLine=new String();
					BufferedReader responseReader=new BufferedReader(new InputStreamReader(in1,"UTF-8"));
					while((readLine=responseReader.readLine())!=null){
						sb.append(readLine).append("\n");
					}
					responseReader.close();
					System.out.println(sb.toString());
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			} else {
				System.out.println("error++");
			}
		} catch (Exception e) {
		}
		return sb.toString();
	}



	public static  Object RestTemplatePOST(String url, String data,Map<String,String> header)
	{
		MultiValueMap<String, String> valueMap = new LinkedMultiValueMap<>();
		valueMap.add("bhs", "true");
		valueMap.add("bym", "true");
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(org.springframework.http.MediaType.APPLICATION_JSON);

		if(!header.isEmpty()){
			for(Map.Entry entry: header.entrySet()) {
				headers.set((String) entry.getKey(),(String) entry.getValue());
			}
		}
		RestTemplate restTemplate=new RestTemplate();
		org.springframework.http.HttpEntity<String> request = new org.springframework.http.HttpEntity<>(data, headers);
		UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url).queryParam("bhs","true").queryParam("bym","true");

		Map<String,Object> map=new HashMap<>();
		map.put("bhs", true);
		map.put("bym", true);

		ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(builder.toUriString(), request, JSONObject.class);

		System.out.println(builder.toUriString());

		return responseEntity;
	}

}
